package com.jghiof.face_recognition;

import com.baidu.aip.face.AipFace;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;

/**
 * 百度人脸识别处理核心
 * 作者：王大傻
 * 时间：2019年9月09日17:38:13
 * 版本：v0.2
 */
public class FaceUtil {

    // 认证参数
    private static final String APP_ID = "24247698";
    private static final String API_KEY = "0ZydKFm1FDhnXZQ1XyDtdy5I";
    private static final String SECRET_KEY = "5RGqUQnHlhSG4pFAGsids7lDcIk6lF3B";

    // 检测人脸附加参数
    private static final String FACE_FIELD = "quality,type,beauty,age";

    // 全局返回状态码
    private static final String SUCCESS = "SUCCESS";

    private static AipFace client = null;

    /**
     * 初始化
     *
     * @return
     */
    static {
        client = new AipFace(APP_ID, API_KEY, SECRET_KEY);
        // 可选：设置网络连接参数
        client.setConnectionTimeoutInMillis(2000);// 建立连接的超时时间（单位：毫秒）
        client.setSocketTimeoutInMillis(60000);// 通过打开的连接传输数据的超时时间（单位：毫秒）
        // 可选：设置代理服务器地址, http和socket二选一，或者均不设置
        // client.setHttpProxy("proxy_host", proxy_port);  // 设置http代理
        // client.setSocketProxy("proxy_host", proxy_port);  // 设置socket代理
    }

    /**
     * 人脸检测
     */
    public JSONObject faceUpload(String image, String imageType) {
        // 传入可选参数调用接口
        HashMap<String, String> options = new HashMap<String, String>();
        options.put("face_field", FACE_FIELD);
        options.put("liveness_control", "LOW");// 活体
        // 发起调用
        JSONObject res = client.detect(image, imageType, options);
        return res;
    }

    /**
     * 解析人脸上传结果
     */
    public JSONObject faceCheck(JSONObject res) throws JSONException {
        // 判断结果
        if (!SUCCESS.equals(res.getString("error_msg"))) {
            res.remove("error_msg");
            res.put("error_msg", "无法识别,请重试!");
            return res;
        }
        JSONObject face_list = res.getJSONObject("result").getJSONArray("face_list").getJSONObject(0);
        // 验证人脸质量
        JSONObject quality = face_list.getJSONObject("quality");
        boolean checkQuality = checkQuality(quality);
        // 验证姿态
        boolean checkAttitude = checkAttitude(face_list);
        if (!(checkQuality && checkAttitude)) {
            res.remove("error_msg");
            res.put("error_msg", "无法识别,请重试!");
            return res;
        }
        return res;
    }

    /**
     * 人脸注册
     */
    public String faceRegister(String image, String imageType, String groupId, String userId, String userInfo) {
        HashMap<String, String> options = new HashMap<String, String>();
        options.put("liveness_control", "LOW");
        options.put("userInfo", userInfo);
        // 人脸注册
        JSONObject res = client.addUser(image, imageType, groupId, userId, options);
        try {
            return res.toString(2);
        } catch (JSONException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 人脸搜索
     */
    public JSONObject faceSearch(String image, String imageType, String groupId, String userId) {
        HashMap<String, String> options = new HashMap<String, String>();
        // 指定user_id进行比对,即人脸认证功能
        options.put("user_id", userId);
        options.put("liveness_control", "LOW");
        // 人脸搜索
        JSONObject res = client.search(image, imageType, groupId, options);
        return res;
    }

    /**
     * 删除人脸
     */
    public void faceDelete(String groupId, String userId, String faceToken) {
        HashMap<String, String> options = new HashMap<String, String>();
        // 人脸删除
        JSONObject res = client.faceDelete(userId, groupId, faceToken, options);
    }

    /**
     * 验证人脸质量
     */
    private boolean checkQuality(JSONObject quality) throws JSONException {
        // 验证遮挡范围
        JSONObject occlusion = quality.getJSONObject("occlusion");
        double leftEye = occlusion.getDouble("left_eye");
        if (leftEye > 0.6) {
            return false;
        }
        double rightEye = occlusion.getDouble("right_eye");
        if (rightEye > 0.6) {
            return false;
        }
        double nose = occlusion.getDouble("nose");
        if (nose > 0.7) {
            return false;
        }
        double mouth = occlusion.getDouble("mouth");
        if (mouth > 0.7) {
            return false;
        }
        double leftCheck = occlusion.getDouble("left_cheek");
        if (leftCheck > 0.8) {
            return false;
        }
        double rightCheck = occlusion.getDouble("right_cheek");
        if (rightCheck > 0.8) {
            return false;
        }
        double chinContour = occlusion.getDouble("chin_contour");
        if (chinContour > 0.6) {
            return false;
        }

        // 模糊度
        double blur = quality.getDouble("blur");
        if (blur > 0.7) {
            return false;
        }

        // 光照范围
        double illumination = quality.getDouble("illumination");
        if (illumination < 40) {
            return false;
        }

        // 人脸完整度
        double completeness = quality.getInt("completeness");
        if (completeness == 0) {
            return false;
        }
        return true;
    }

    /**
     * 验证姿态
     */
    private boolean checkAttitude(JSONObject face_list) throws JSONException {
        // 姿态角度
        JSONObject angle = face_list.getJSONObject("angle");
        double roll = angle.getDouble("roll");
        if (roll <= -20 || roll >= 20) {
            return false;
        }
        double pitch = angle.getDouble("pitch");
        if (pitch <= -20 || pitch >= 20) {
            return false;
        }
        double yaw = angle.getDouble("yaw");
        if (yaw <= -20 || yaw >= 20) {
            return false;
        }

        // 人脸大小
        JSONObject location = face_list.getJSONObject("location");
        int width = location.getInt("width");
        int height = location.getInt("height");
        if (width < 100 || height < 100) {
            return false;
        }
        return true;
    }

    public static void main(String[] args) throws JSONException {
        String image = "http://5b0988e595225.cdn.sohucs.com/images/20180604/cf9acd5afbe147c2957bf1d5989335d6.jpeg";
        String imageType = "URL";
        FaceUtil faceUtil = new FaceUtil();
        JSONObject jsonObject = faceUtil.faceUpload(image, imageType);
        System.out.println(jsonObject.toString(2));

        JSONObject res = faceUtil.faceCheck(jsonObject);
        System.out.println(res.getString("error_msg"));
        JSONObject face_list = jsonObject.getJSONObject("result").getJSONArray("face_list").getJSONObject(0);
        if (SUCCESS.equals(res.get("error_msg"))) {
            String s = faceUtil.faceSearch(face_list.getString("face_token"), "FACE_TOKEN", "test_1", "999").toString(2);
            System.out.println(s);
        }
    }
}